package org.compiere.process;

import java.math.BigDecimal;
import java.math.MathContext;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;

import org.adempiere.exceptions.DBException;
import org.compiere.apps.ADialog;
import org.compiere.model.MPrepaidExpenses;
import org.compiere.model.MFactAcct;
import org.compiere.model.MJournal;
import org.compiere.model.MJournalBatch;
import org.compiere.model.MJournalLine;
import org.compiere.model.MPeriod;
import org.compiere.model.MSequence;
import org.compiere.model.X_A_Depreciation_Build;
import org.compiere.model.X_FI_PrepaidExpensesLine;
import org.compiere.model.X_GL_Category;
import org.compiere.util.DB;
import org.compiere.util.Env;
import org.joda.time.DateTime;

/*
 *  Add by Ibraev E.A.
 *  Created: 13.09.2012
 *  
 *  Процесс закрытия периода, для РБП (расчеты будущих периодов)
 * 
 * 
 */

public class CFPCloseMonth extends SvrProcess {

	private int C_Period_ID = 0;
	private int p_AD_Client_ID;
	private int p_AD_Org_ID;
	private int c_conversiontype_id = 0;
	private int gl_category_id = 0;
	private int c_currency_id = 0;
	private int c_doctype_id = 0;
	private String description = null;
	private String documentNo = null;
	
	private String resultIt = null;
	
	MJournalBatch batch = null;
	
	@Override
	protected void prepare() {
		StringBuffer sql = new StringBuffer();
		String clientCheck = " AND AD_Client_ID=" + getAD_Client_ID();
		
		getProcessInfo();
		initParameters();
		p_AD_Client_ID = Env.getAD_Client_ID(getCtx());
		p_AD_Org_ID = Env.getAD_Org_ID(getCtx());
	 	Env.getAD_User_ID(getCtx());
	 	c_doctype_id = getC_DocType_ID();
	 	getBatchID(C_Period_ID);
		sql.setLength(0);
        sql.append("SELECT GL_Category_ID FROM GL_Category "
		+ " WHERE isActive='Y' AND CategoryType = '"+X_GL_Category.CATEGORYTYPE_Manual+"'"
        +" AND isDefault = 'Y'"+clientCheck);
        gl_category_id = DB.getSQLValue(get_TrxName(), sql.toString());

		c_currency_id = getC_Currency_ID();
		
		//Set Conversion Type
		sql.setLength(0);
		sql.append("SELECT C_ConversionType_ID FROM C_ConversionType "
		+ " WHERE isActive='Y' AND isDefault = 'Y' AND NAME = 'Daily'");
		c_conversiontype_id = DB.getSQLValue(get_TrxName(), sql.toString());
		
//		c_conversiontype_id = 114;
		
	}

	@Override
	protected String doIt() throws Exception {
/*		
		if (IncomeExpedentureCloseMonth(C_Period_ID)) {
			log.info("Month is closed");
			resultIt = "Месяц уже закрыт!";
		}
		else
*/			
		if ( cfpIsOpen(C_Period_ID) 
		       && CreateEntries(C_Period_ID) ) {
			resultIt = "РБП по данному периоду закрыт"; 
		} 
		return resultIt;
	}
	
	private void initParameters() {
		for(ProcessInfoParameter param: getParameter()) {
			if (param.getParameterName().equals("C_Period_ID")) {
				C_Period_ID = Integer.parseInt(param.getParameter().toString());
			}
		}
	}
	
	private Boolean IncomeExpedentureCloseMonth(int C_Period_ID) {
		Boolean result = false;
		StringBuffer sql = new StringBuffer();
		String clientCheck = " AND AD_Client_ID=" + getAD_Client_ID();
		
		sql.setLength(0);
        sql.append("SELECT C_DocType_ID FROM C_DocType"
		+ " WHERE Name='Closing of income and expenditure' AND DocBaseType='GLJ' AND isActive ='Y'"+clientCheck);        
        int c_doctype_id = DB.getSQLValue(get_TrxName(), sql.toString());
		if (c_doctype_id<0) return result ;
		
		sql.setLength(0);
		sql.append("SELECT GL_JournalBatch_ID FROM ADEMPIERE.GL_JournalBatch WHERE DOCSTATUS = 'CO' AND C_PERIOD_ID = " + String.valueOf(C_Period_ID)
				+ " AND C_DOCTYPE_ID = " + c_doctype_id);
		int batchID = DB.getSQLValue(get_TrxName(), sql.toString());
		
		result = (batchID > 0);
		
		return result;
	}
	
	private boolean cfpIsOpen(int C_Period_ID) {
		if (c_doctype_id<0) {
			log.info("doctype is not found");
			return false;
		}
		ADialog dialog = new ADialog();
		if(getBatchID(C_Period_ID) > 0) {
			if(!dialog.ask(25, null, "Процесс \"Закрытие месяца. РБП\" уже был успешно завершен. Вы хотите запустить данный процесс повторно?")) {
				resultIt = "отмена перезакрытия РБП";
				return false;
			}
			else {
				return ClearBatch(C_Period_ID);
			}
		}
		return true;
	}

	private MPrepaidExpenses[] getFI_PrepaidExpenses(int C_Period_ID) {
		List<MPrepaidExpenses> result = new ArrayList<MPrepaidExpenses>();
	    PreparedStatement pstmt = null;
		ResultSet rs = null;
		try {
			String query = getSql(C_Period_ID);
			pstmt = DB.prepareStatement(query,null);
			rs = pstmt.executeQuery();	
			while(rs.next()) {
				MPrepaidExpenses current = new MPrepaidExpenses(getCtx(),rs,null);
				if (haveC_Invoice(current)) {
					result.add(current);
				}
			}
		} 
		catch (SQLException e) {
			log.log(Level.SEVERE, "product", e);
			return null;
		} 
		finally {
			DB.close(rs, pstmt);
			rs = null; pstmt = null;
		}	
		return (MPrepaidExpenses[]) (result.size() == 0 ? null : result.toArray(new MPrepaidExpenses[result.size()]));
	}

	private String getSql(int C_Period_ID) {
		String result = null;
		Timestamp BeginPeriod = getPeriod(C_Period_ID).getStartDate();
		Timestamp EndPeriod = getPeriod(C_Period_ID).getEndDate();
		result = "SELECT * FROM FI_PrepaidExpenses WHERE IsActive='Y' and (DocStatus = '"+MPrepaidExpenses.DOCSTATUS_Completed+"' or DocStatus = '"+MPrepaidExpenses.DOCSTATUS_InProgress+"') and posted='Y' and datefrom <= '" + EndPeriod.toString() + "' and '" + BeginPeriod.toString() + "' <= dateto";
		return result;
	}
	
	private int getC_DocType_ID() {
		int result = 0;
		StringBuffer sql = new StringBuffer();
		String clientCheck = " AND AD_Client_ID=" + getAD_Client_ID();
		
		sql.setLength(0);
        sql.append("SELECT C_DocType_ID FROM C_DocType"
		+ " WHERE Name='Prepaid Expenses' AND isActive ='Y'"+clientCheck);
/*		        
		sql.setLength(0);
        sql.append("SELECT C_DocType_ID FROM C_DocType"
		+ " WHERE Name='GL Journal' AND isActive ='Y'"+clientCheck);
*/		
        result = DB.getSQLValue(get_TrxName(), sql.toString());
        
		return result;
	}
	
	private int getBatchID(int C_Period_ID) {
		int result = 0;
		StringBuffer sql = new StringBuffer();
		sql.setLength(0);		
		sql.append("SELECT GL_JournalBatch_ID FROM ADEMPIERE.GL_JournalBatch WHERE DOCSTATUS = 'CO' AND C_PERIOD_ID = " + String.valueOf(C_Period_ID)
				+ " AND C_DOCTYPE_ID = " + c_doctype_id);
		result = DB.getSQLValue(get_TrxName(), sql.toString());
		return result;
	}
	
	private boolean CreateEntries(int C_Period_ID) {
		boolean result = true;
		MPrepaidExpenses[] FI_PrepaidExpenses = getFI_PrepaidExpenses(C_Period_ID);
		result = (null != FI_PrepaidExpenses);
		if (result) {
			batch = getBatch(C_Period_ID);
			for(MPrepaidExpenses current: FI_PrepaidExpenses) {
				if ( haveC_Invoice(current)) {
					result = result && CreateLine(current);
				}
			}
		}
		else {
			ADialog.info(25, null, "Нет документов для процесса \"Закрытие месяца. РБП\".\n Записи в \"Главный журнал\" не будут произведены");
		}
		return result;
	}
	
	protected MJournalBatch getBatch(int C_Period_ID) {
		MJournalBatch result = null;
		if ( getBatchID(C_Period_ID) > 0) {
			result = new MJournalBatch(getCtx(), getBatchID(C_Period_ID), null);
			String dn = MSequence.getDocumentNo (p_AD_Client_ID, "gl_journalbatch", get_TrxName(), result);
			documentNo = dn;
			description = dn;
			if (documentNo == null) {
				throw new DBException ("No DocumentNo");
			}
		}
		else {
			result  = createBatch(C_Period_ID);
		}
			
		return result;
	}
	
	protected MJournalBatch createBatch(int C_Period_ID) {
		MJournalBatch result = new MJournalBatch(getCtx(), getBatchID(C_Period_ID), null);
		
		String dn = MSequence.getDocumentNo (p_AD_Client_ID, "gl_journalbatch", get_TrxName(), result);
		documentNo = dn;
		description = dn;

		if (documentNo == null) {
			throw new DBException ("No DocumentNo");
		}
		
		result.setClientOrg(p_AD_Client_ID, p_AD_Org_ID);
		result.setDocumentNo(documentNo);
		result.setDescription(description);
		result.setPostingType(X_A_Depreciation_Build.POSTINGTYPE_Actual);
		result.setGL_Category_ID(gl_category_id);
		result.setDateDoc(getPeriod(C_Period_ID).getEndDate());
		result.setDateAcct(getPeriod(C_Period_ID).getEndDate());
		result.setC_Period_ID(C_Period_ID);
		result.setC_Currency_ID(c_currency_id);
		result.setControlAmt(BigDecimal.valueOf(0));
		result.setC_DocType_ID(c_doctype_id);
		result.setDocStatus(MJournalBatch.STATUS_InProgress);
		result.setDocAction(MJournalBatch.ACTION_Prepare);
		result.setProcessing(true);
		result.setProcessed(true);
		
		if (!result.save()) {
			log.log(Level.SEVERE, "Batch Journal not saved - " + documentNo);
			return null;
		}
		
		return result;
	}
	
	protected boolean CreateLine(MPrepaidExpenses current) {
		boolean result = true;
		
		if (batch == null) {
			result = false;
			return result;
		}
		
		int ad_table2 = getAD_Table_ID("GL_Journal");
		int accountID1 = getAccountID(current,true); // 162000
		int accountID2 = getAccountID(current,false);// C_BPartner acct
		int validation1 = getValidation(accountID1); // 162000
		int validation2 = getValidation(accountID2); // C_BPartner acct
		BigDecimal amount = current.getMonthAmount(new Date(batch.getDateAcct().getTime()));
		int C_AcctSchema_ID = Env.getContextAsInt(getCtx(),"$C_AcctSchema_ID");
					
		if (documentNo == null) {
			result = false;
			throw new DBException ("No DocumentNo");
		}
		
		String documentNo2 = documentNo + " - " + current.getDocumentNo();

		
		MJournal journal = new MJournal(batch);
		
		journal.setClientOrg(getAD_Client_ID(), p_AD_Org_ID);
		journal.setIsActive(true);
		journal.setC_AcctSchema_ID(C_AcctSchema_ID);
		journal.setC_DocType_ID(batch.getC_DocType_ID());
		journal.setDocumentNo(documentNo2);
		journal.setDocStatus(MJournalBatch.STATUS_InProgress);
		journal.setDocAction("--");
		journal.setIsApproved(true);
		journal.setIsPrinted(false);
		journal.setDescription(description);
		journal.setPostingType(batch.getPostingType());
		journal.setGL_Category_ID(batch.getGL_Category_ID());
		journal.setDateDoc(batch.getDateDoc());
		journal.setDateAcct(batch.getDateAcct());
		journal.setC_Period_ID(batch.getC_Period_ID());
		journal.setCurrencyRate(new BigDecimal(1));
		journal.setControlAmt(new BigDecimal(0));
		journal.setC_ConversionType_ID(c_conversiontype_id);
		journal.setProcessing(true);
		journal.setProcessed(true);
		journal.setPosted(true);
		
		if (!journal.save()) {
			log.log(Level.SEVERE, "Journal not saved - "+batch.getDocumentNo()+ " " +journal.getDocumentNo());
			result = false;
		}
		
		
		MJournalLine line1 = new MJournalLine(journal);
		MJournalLine line2 = new MJournalLine(journal);
		
		line1.setAD_Org_ID(p_AD_Org_ID);
		line1.setLine(10);
		line1.setAmtSourceCr(new BigDecimal(0));
		line1.setAmtSourceDr(amount);
		line1.setAmtAcctCr(new BigDecimal(0));
		line1.setAmtAcctDr(amount);
		line1.setCurrency(journal.getC_Currency_ID(), journal.getC_ConversionType_ID(), new BigDecimal(1));
		line1.setDateAcct(journal.getDateAcct());
		line1.setC_ValidCombination_ID(validation2);
		line1.setProcessed(true);
		line1.setA_CreateAsset(false);
		line1.setA_Processed(false);
		line1.setC_Charge_ID(current.getC_Charge_ID());
		if (!line1.save()) {
			log.log(Level.SEVERE, "Line number one not saved - " + batch.getDocumentNo()+ " " +line1.getDescription());
			result = false;
		}
				
		MJournalLine.copyValues(line1, line2);
		
		line2.setAmtSourceCr(amount);
		line2.setAmtSourceDr(new BigDecimal(0));				
		line2.setAmtAcctCr(amount);
		line2.setAmtAcctDr(new BigDecimal(0));
		line2.setC_ValidCombination_ID(validation1);
		line2.setC_Charge_ID(0);
		if (!line2.save()) {
			log.log(Level.SEVERE, "Line number one not saved - " + batch.getDocumentNo()+ " " +line2.getDescription());
			result = false;
		}
				
		MFactAcct fact = new MFactAcct(getCtx(), 0, get_TrxName());					

		fact.setAD_Org_ID(p_AD_Org_ID);
		fact.setC_AcctSchema_ID(journal.getC_AcctSchema_ID());
		fact.setC_Period_ID(journal.getC_Period_ID());		
		fact.setAmtSourceCr(new BigDecimal(0));
		fact.setAmtSourceDr(amount);
		fact.setAmtAcctCr(new BigDecimal(0));
		fact.setAmtAcctDr(amount);
		fact.setDateAcct(journal.getDateAcct());
		fact.setDateTrx(journal.getDateDoc());
		fact.setRecord_ID(journal.get_ID());
		fact.setC_BPartner_ID(0);
		fact.setAD_Table_ID(ad_table2);
		fact.setAccount_ID(accountID2);
		fact.setLine_ID(line1.get_ID());
		fact.setPostingType(journal.getPostingType());
		fact.setC_Currency_ID(journal.getC_Currency_ID());
		fact.set_ValueOfColumn("Reference", 1);
		fact.set_ValueOfColumn("Counter", 2);
		if (!fact.save()) {
			log.log(Level.SEVERE, "Line number one not saved - " + batch.getDocumentNo()+ " " +fact.getDescription());
			result = false;
		}
					
		MFactAcct fact2 = new MFactAcct(getCtx(), 0, get_TrxName());	
		MFactAcct.copyValues(fact, fact2);
		fact2.setAmtSourceDr(new BigDecimal(0));
		fact2.setAmtSourceCr(amount);
		fact2.setAmtAcctDr(new BigDecimal(0));
		fact2.setAmtAcctCr(amount);
		fact2.setRecord_ID(journal.get_ID());
		fact2.setDateAcct(journal.getDateAcct());
		fact2.setDateTrx(journal.getDateDoc());

		fact2.setAD_Table_ID(ad_table2);
		fact2.setAccount_ID(accountID1);
		fact2.setC_BPartner_ID(0);
		fact2.set_ValueOfColumn("Reference", 2);
		fact2.set_ValueOfColumn("Counter", 1);
		if (!fact2.save()) {
			log.log(Level.SEVERE, "Line number one not saved - " + batch.getDocumentNo()+ " " +fact2.getDescription());
			result = false;
		}
				
//		MathContext context = new MathContext(7);
		
//		journal.setTotalCr(amount.round(context));
//		journal.setTotalDr(amount.round(context));
		journal.setTotalCr(amount);
		journal.setTotalDr(amount);
		
//		BigDecimal batchTotalCr = batch.getTotalCr().add(amount.round(context), context);
//		BigDecimal batchTotalDr = batch.getTotalDr().add(amount.round(context), context);
		BigDecimal batchTotalCr = batch.getTotalCr().add(amount);
		BigDecimal batchTotalDr = batch.getTotalDr().add(amount);

		batch.setTotalCr(batchTotalCr);
		batch.setTotalDr(batchTotalDr);
		
		journal.setDocStatus(MJournalBatch.STATUS_Completed);
		batch.setDocStatus(MJournalBatch.STATUS_Completed);
		
		if (!journal.save()) {
			log.log(Level.SEVERE, "Line number one not saved - " + batch.getDocumentNo()+ " " +journal.getDocumentNo());
			result = false;
		}
		
		if (!batch.save()) {
			log.log(Level.SEVERE, "Line number one not saved - " + batch.getDocumentNo());
			result = false;
		}
		
		if (result) {
			current.setGL_Journal(journal, C_Period_ID);
			current.setDocStatus(MPrepaidExpenses.DOCSTATUS_InProgress);
			if (!current.save()) {
				log.log(Level.SEVERE, "Document status not changed - " + current.getDocumentNo());
			}
		}

		return result;
	}
	
	protected MPeriod getPeriod(int C_Period_ID) {
		MPeriod period = new MPeriod(getCtx(), C_Period_ID, null);
		return period;
	}
	
	private int getAD_Table_ID(String tableName) {
		String sql = "SELECT AD_Table_ID from AD_Table WHERE TableName = ?";
		int result = DB.getSQLValue(get_TrxName(), sql, tableName);
		return result;
	}
	
	private int getValidation(int accountID) {
		String sql = "SELECT c_validcombination_id FROM c_validcombination WHERE C_BPartner_ID is null and isActive='Y' AND account_id = " + accountID + " and ad_org_id = " + p_AD_Org_ID + " AND AD_Client_ID=" + getAD_Client_ID();
		int result = DB.getSQLValue(get_TrxName(), sql);
		return result;
	}
	
	private int getAccountID(MPrepaidExpenses current, Boolean Var) {
		int result = -1;
		if (Var) {
			String sql = null;
			sql = "SELECT Account_ID FROM C_ValidCombination WHERE C_ValidCombination_ID in (SELECT V_PrepaidExpenses_Acct C FROM C_BP_Vendor_Acct WHERE C_BPartner_ID=? AND C_AcctSchema_ID=?)";
			if (sql != null) {
				int para_1 = current.getC_BPartner_ID();
				int para_2 = Env.getContextAsInt(getCtx(),"$C_AcctSchema_ID");
				result = DB.getSQLValue(get_TrxName(), sql, para_1, para_2);
			}
		}
		else {
			result = current.getChargeAccount().getAccount_ID();
		}
		return result;
	}
	
	private Boolean haveC_Invoice(MPrepaidExpenses current) {
		Boolean result = false;
		if (current.getC_InvoiceLine() != null) {
			result = true;
		}
		return result;
	}
	
	private int getC_Currency_ID() {
		int result = 0;
		String sql ="SELECT C_Currency_ID FROM C_AcctSchema WHERE isActive='Y' and AD_Client_ID = ?";
        result = DB.getSQLValue(get_TrxName(), sql, getAD_Client_ID());
		return result;
	}
	
	private Boolean ClearBatch(int C_Period_ID) {
		
		Boolean result = true;
		batch = null;
		batch = new MJournalBatch(getCtx(), getBatchID(C_Period_ID), null);
		
		if (batch == null) {
			resultIt = "Нет закрытого РБП для периода";
			result = false;
			return result;
		}
		int C_AcctSchema_ID = Env.getContextAsInt(getCtx(),"$C_AcctSchema_ID");
		
		MJournal[] journals = batch.getJournals(true);
		
		batch.setDocStatus(MJournalBatch.STATUS_InProgress);
		
		batch.setDocAction(MJournalBatch.ACTION_Complete);
		
		batch.save();
		
		String dn = MSequence.getDocumentNo (p_AD_Client_ID, "gl_journalbatch", get_TrxName(), batch);
		if (dn == null)
			throw new DBException ("No DocumentNo");
		
		documentNo = dn;
		
		MJournalBatch batch2 = new MJournalBatch(getCtx(), null, get_TrxName());
		batch2.setClientOrg(p_AD_Client_ID, p_AD_Org_ID);
		batch2.setDocumentNo(documentNo);
		batch2.setDescription(batch.getDocumentNo());
		batch2.setPostingType(X_A_Depreciation_Build.POSTINGTYPE_Actual);
		batch2.setGL_Category_ID(batch.getGL_Category_ID());
		batch2.setDateDoc(batch.getDateDoc());
		batch2.setDateAcct(batch.getDateAcct());
		batch2.setC_Period_ID(batch.getC_Period_ID());
		batch2.setC_Currency_ID(batch.getC_Currency_ID());
		batch2.setControlAmt(BigDecimal.valueOf(0));
		batch2.setC_DocType_ID(batch.getC_DocType_ID());
		batch2.setProcessing(true);
		batch2.setProcessed(true);
		
		batch2.setDocStatus(MJournalBatch.STATUS_InProgress);
		batch2.setDocAction(MJournalBatch.ACTION_Prepare);
		if (!batch2.save()) {
			log.log(Level.SEVERE, "Journal not saved - "+batch.getDocumentNo()+ " " +batch2.getDocumentNo());
			result = false;
		} 
		
		batch.setDescription(documentNo);
		Integer i = 0;
		for(MJournal oldJournal:journals) {
			
			MJournalLine[] lines = oldJournal.getLines(true);
			MJournal journal = new MJournal(batch2);
			
			journal.setClientOrg(getAD_Client_ID(), p_AD_Org_ID);
			journal.setIsActive(true);
			journal.setC_AcctSchema_ID(1000000);
			journal.setC_DocType_ID(batch.getC_DocType_ID());
			journal.setDocumentNo(batch.getDocumentNo() + (++i).toString());
			journal.setDocStatus(batch.getDocStatus());
			journal.setDocAction("--");
			journal.setIsApproved(true);
			journal.setIsPrinted(false);
			journal.setDescription(batch.getDescription());
			journal.setPostingType(batch.getPostingType());
			journal.setGL_Category_ID(batch.getGL_Category_ID());
			journal.setDateDoc(batch.getDateDoc());
			journal.setDateAcct(batch.getDateAcct());
			journal.setC_Period_ID(batch.getC_Period_ID());
			journal.setCurrencyRate(new BigDecimal(1));
			journal.setControlAmt(new BigDecimal(0));
			journal.setC_ConversionType_ID(c_conversiontype_id); // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
			journal.setProcessing(true);
			journal.setProcessed(true);
			journal.setPosted(true);
			
			if (!journal.save()) {
				log.log(Level.SEVERE, "Journal not saved - "+batch.getDocumentNo()+ " " +journal.getDocumentNo());
				result = false;
			} 
			
			boolean b = true;
			for (MJournalLine line : lines) 
			{
				MJournalLine newLine = new MJournalLine(journal);
									
				newLine.setAD_Org_ID(p_AD_Org_ID);
				newLine.setIsActive(true);
				newLine.setLine(100);
				newLine.setCurrency(341, 114, new BigDecimal(1));
				newLine.setDateAcct(journals[0].getDateAcct());
				newLine.setC_ValidCombination_ID(line.getC_ValidCombination_ID());
				newLine.setProcessed(true);
				newLine.setA_CreateAsset(false);
				newLine.setA_Processed(false);
				
				newLine.setAmtAcctCr(line.getAmtAcctCr().negate());
				newLine.setAmtAcctDr(line.getAmtAcctDr().negate());			
				newLine.setAmtSourceCr(line.getAmtSourceCr().negate());
				newLine.setAmtSourceDr(line.getAmtSourceDr().negate()); //TODO

				newLine.save();
				
				MFactAcct acct = new MFactAcct(getCtx(), null, get_TrxName());
				acct.setAmtAcctCr(line.getAmtAcctCr().negate());
				acct.setAmtAcctDr(line.getAmtAcctDr().negate());					
				acct.setAmtSourceCr(line.getAmtSourceCr().negate());
				acct.setAmtSourceDr(line.getAmtSourceDr().negate());
				acct.setAccount_ID(line.getAccount().getAccount_ID());
				acct.setC_AcctSchema_ID(C_AcctSchema_ID);
				acct.setC_Period_ID(C_Period_ID);
				acct.setAD_Table_ID(getAD_Table_ID("GL_Journal")); // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
				acct.setRecord_ID(journal.get_ID());
				acct.setGL_Category_ID(batch.getGL_Category_ID()); //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
				acct.setC_Currency_ID(journal.getC_Currency_ID()); //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
				acct.setDateAcct(journal.getDateAcct());
				acct.setDateTrx(journal.getDateAcct());
				acct.setPostingType("A");
				if (b) {
					acct.set_ValueOfColumn("Reference", 1);
					acct.set_ValueOfColumn("Counter", 2);
					b = false;
				} else {
					acct.set_ValueOfColumn("Reference", 2);
					acct.set_ValueOfColumn("Counter", 1);
					b = true;
				}
				acct.save();
			}
			
			oldJournal.setDocStatus(MJournalBatch.STATUS_Voided);
			journal.setDocStatus(MJournalBatch.STATUS_Reversed);
			oldJournal.setDocAction(MJournalBatch.ACTION_Reject);
			journal.setDocAction(MJournalBatch.ACTION_Reject);
			if (!oldJournal.save()) {
				log.log(Level.SEVERE, "Journal not saved - "+batch.getDocumentNo()+ " " +oldJournal.getDocumentNo());
				result = false;
			} 
			else {
				ClearFI_PrepaidExpensesLine(oldJournal.getGL_Journal_ID(),C_Period_ID);
			}
			
			if (!journal.save()) {
				log.log(Level.SEVERE, "Journal not saved - "+batch.getDocumentNo()+ " " +journal.getDocumentNo());
				result = false;
			} 
		}
		
		documentNo = "";
		batch.setDocStatus(MJournalBatch.STATUS_Voided);
		batch2.setDocStatus(MJournalBatch.STATUS_Reversed);
		
		batch.setDocAction(MJournalBatch.ACTION_Reject);
		batch2.setDocAction(MJournalBatch.ACTION_Reject);

		
		if (!batch2.save()) {
			log.log(Level.SEVERE, "Journal not saved - "+batch2.getDocumentNo());
			result = false;
		} 
		if (!batch.save()) {
			log.log(Level.SEVERE, "Journal not saved - "+batch.getDocumentNo());
			result = false;
		} 
		
		return result;
	}
	
	private void ClearFI_PrepaidExpensesLine(int GL_Journal_ID, int C_Period_ID) {
	    PreparedStatement pstmt = null;
		ResultSet rs = null;
		try {
			String query = "SELECT FI_PrepaidExpensesLine_ID FROM FI_PrepaidExpensesLine WHERE AD_Client_ID = ? and GL_Journal_ID = ? and C_Period_ID = ? and IsActive = 'Y'";
			pstmt = DB.prepareStatement(query,null);
			pstmt.setInt(1, getAD_Client_ID());
			pstmt.setInt(2, GL_Journal_ID);
			pstmt.setInt(3, C_Period_ID);
			rs = pstmt.executeQuery();	
			if (rs.next()) {
				Integer FI_PrepaidExpensesLine_ID = rs.getInt(1);
				if (FI_PrepaidExpensesLine_ID != null) {
					X_FI_PrepaidExpensesLine FI_PrepaidExpensesLine = new X_FI_PrepaidExpensesLine(getCtx(),FI_PrepaidExpensesLine_ID, null);
					FI_PrepaidExpensesLine.setIsActive(false);
					if (!FI_PrepaidExpensesLine.save()) {
						log.log(Level.WARNING, "Can't make an active - " + FI_PrepaidExpensesLine.getFI_PrepaidExpensesLine_ID());
					}
				}
			}
			
		} 
		catch (SQLException e) {
			log.log(Level.SEVERE, "product", e);
			return;
		} 
		finally {
			DB.close(rs, pstmt);
			rs = null; pstmt = null;
		}	
		return;
	}
}
